/*
 * policy_parse.c
 *
 *  Created on: Nov 17, 2010
 *      Author: leopold
 */

#include <stdio.h>
#include <stdlib.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xmlstring.h>
#include <libxml/globals.h>
#include <errno.h>
#include <string.h>
#include "pdb/policy_parse.h"
#include "pdb/pm.h"
//2012-07-15
#include "pdb/policy_table.h"
//2012-07-15
#define	ERANGE		34	/* Math result not representable */

static struct list_head policy_head = {&(policy_head), &(policy_head)};

static int parse_policy(xmlDocPtr doc, xmlNodePtr node)
{
	int version = 0;
	int operation = 0;
	int up_limit = 0;
	int lower_limit = 0;
	unsigned long long value1 = 0;
	unsigned long long value2 = 0;

#define INIT_VARS() \
({\
	operation = 0;\
	up_limit = 0;\
	lower_limit = 0;\
	value1 = 0;\
	value2 = 0;\
})

	xmlNodePtr cur_node = NULL;
	xmlNodePtr child_node = NULL;

	char *endptr = NULL;
	int base = 10;

	struct policy_head * policy_ptr = NULL;

	for (cur_node = node->children; cur_node!= NULL; cur_node = cur_node->next) {
		if (cur_node->type == XML_ELEMENT_NODE) {
			if (xmlStrcmp(cur_node->name, (const xmlChar *)(VERSION)) == 0) {
				xmlChar * value = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
				version = strtol((char *)value, &endptr, base);
				if ((errno == ERANGE )
						|| (errno != 0 && version == 0)) {
					DEBUG(ERROR, "get value version failed.");
					return -1;
				}
				xmlFree(value);
			}else {
				for (child_node = cur_node->children; child_node!= NULL; child_node = child_node->next) {
					if (child_node->type == XML_ELEMENT_NODE) {
						if (xmlStrcmp(child_node->name, (const xmlChar *)(OPERATION)) == 0) {
							xmlChar * value = xmlNodeListGetString(doc, child_node->xmlChildrenNode, 1);
							operation = strtol((char *)value, &endptr, base);
							if ((errno == ERANGE )
									|| (errno != 0 && operation == 0)) {
								DEBUG(ERROR, "get value operation failed.");
								return -1;
							}
							xmlFree(value);
						}
						if (xmlStrcmp(child_node->name, (const xmlChar *)(UP_LIMIT)) == 0) {
							xmlChar * value = xmlNodeListGetString(doc, child_node->xmlChildrenNode, 1);
							up_limit = strtol((char *)value, &endptr, base);
							if ((errno == ERANGE )
									|| (errno != 0 && up_limit == 0)) {
								DEBUG(ERROR, "get value up_limit failed.");
								return -1;
							}
							xmlFree(value);
						}
						if (xmlStrcmp(child_node->name, (const xmlChar *)(LOWER_LIMIT)) == 0) {
							xmlChar * value = xmlNodeListGetString(doc, child_node->xmlChildrenNode, 1);
DEBUG(INFO,"value = %s",value);
							lower_limit = strtol((char *)value, &endptr, base);
DEBUG(INFO,"lower_limit == %d",lower_limit);
							if ((errno == ERANGE )
									|| (errno != 0 && lower_limit == 0)) {
								DEBUG(ERROR, "get value lower_limit failed.");
								return -1;
							}
							xmlFree(value);
						}
						if (xmlStrcmp(child_node->name, (const xmlChar *)(VALUE1)) == 0) {
							xmlChar * value = xmlNodeListGetString(doc, child_node->xmlChildrenNode, 1);
							value1 = strtoull((char *)value, &endptr, base);
		/*******************
							if ( (errno == ERANGE )|| (errno != 0) ) 
							{
								DEBUG(ERROR, "get value value1 failed.");
								return -1;
							}
		*******************/	
							xmlFree(value);
						}
						if (xmlStrcmp(child_node->name, (const xmlChar *)(VALUE2)) == 0) {
							xmlChar * value = xmlNodeListGetString(doc, child_node->xmlChildrenNode, 1);
							value2 = strtoull((char *)value, &endptr, base);
				/**************
							if ((errno == ERANGE ) || (errno != 0) ) 
							{
								DEBUG(ERROR, "get value value2 failed.");
								return -1;
							}
				**************/
							xmlFree(value);
						}
					}
				}
				if (operation == POLICY_FRR) 
				{
				} 
				else if (operation == POLICY_TIMER) 
				{
					//2012-07-15
					struct _policy_element new_policy;

					new_policy.operation = operation;
					new_policy.up_limit = up_limit;
					new_policy.lower_limit = lower_limit;
					new_policy.value[0] = value1;
					new_policy.value[1] = value2;

					add_policy( g_pt, &new_policy );
					//2012-07-15
				}
				//当operation=OPS_PMA_COMPLEX_DDC时,得到调节因子和全网的吞吐率
				else if( operation == COMPLEX_DDC_FLAG )
				{
					ddc_flag = 1;
					param = value1;
					throughput = value2;
				}
			}
		}
	}
	return 0;
}

int process_policy(char * xml, int len)
{
	xmlDocPtr doc = NULL;
	xmlNodePtr root_node = NULL;

	// 	doc = xmlParseFile(argv[1]);
	doc = xmlParseDoc((xmlChar *)xml);
	//doc = xmlParseMemory( xml, len );
	if (doc == NULL) {
		DEBUG(ERROR, "xmlParseDoc failed %s", strerror(errno));
		return -1;
	}

	root_node = xmlDocGetRootElement(doc);
	if (root_node == NULL) {
		DEBUG(ERROR, "xmlDocGetRootElement failed %s", strerror(errno));
		return -1;
	}

	init_policy_table( g_pt );

	if (parse_policy(doc, root_node) != 0) {
		DEBUG(ERROR, "Can't parse the policy.");
		return -1;
	}

	print_policy_table( g_pt );

	xmlFreeDoc(doc);
	xmlCleanupParser();
	return 0;
}
